package com.xxwu.springgobang.model;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.xxwu.springgobang.SpringGobangApplication;
import com.xxwu.springgobang.component.GameRequest;
import com.xxwu.springgobang.component.GameResponds;
import com.xxwu.springgobang.component.OnlineUserManager;
import com.xxwu.springgobang.component.RoomManager;
import com.xxwu.springgobang.mapper.UserMapper;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.IOException;
import java.util.UUID;

@Slf4j
@Data
public class Room {
    private String roomId;
    private User user1;
    private User user2;
    private Integer isWhite;

    private static final int MAX_ROW = 15;
    private static final int MAX_COL = 15;
    //为棋盘设定三种状态
    //0 没有落子
    //1 玩家1落子
    //2 玩家2落子
    private int[][] chessBoard = new int[15][15];


    //这里不能再使用Resource注入，因为Room类并没有交给Spring进行管理，无法注入依赖
    //只用构造方法进行注入
//    @Resource
//    private ObjectMapper objectMapper;

//    @Resource
    private OnlineUserManager onlineUserManager;

//    @Resource
    private RoomManager roomManager;

    private UserMapper userMapper;

    //使用UUID(一个不会重复的字符串)来标识房间号
    public Room(){
        roomId = UUID.randomUUID().toString();
        roomManager = SpringGobangApplication.context.getBean(RoomManager.class);
        onlineUserManager = SpringGobangApplication.context.getBean(OnlineUserManager.class);
        userMapper = SpringGobangApplication.context.getBean(UserMapper.class);
    }

    public void putChess(String reqJson) throws IOException {
        ObjectMapper objectMapper = new ObjectMapper();
        GameRequest req = objectMapper.readValue(reqJson, GameRequest.class);
        GameResponds resp = new GameResponds();
        //1 判断当前子是谁落的，以此来决定忘棋盘中添加元素几
        int chess = req.getUserId() == user1.getUserId() ? 1 : 2;
        int row = req.getRow();
        int col = req.getCol();
        if(chessBoard[row][col] != 0){
            log.info("当前落子位置不为空{}", chessBoard[row][col]);
            return;
        }
        chessBoard[row][col] = chess;

        // 打印棋盘信息
//        printChessBoard();

        //2 进行胜负判定
        int winner = checkWinner(row, col, chess);

        //3 给所有客户端返回响应
        resp.setWinner(winner);
        resp.setUserId(req.getUserId());
        resp.setRow(row);
        resp.setCol(col);
        resp.setMessage("putChess");
        WebSocketSession session1 = onlineUserManager.getSessionFromGameRoom(user1.getUserId());
        WebSocketSession session2 = onlineUserManager.getSessionFromGameRoom(user2.getUserId());



    //玩家下线处理
       if(session1 == null){
            //若玩家1下线则直接判定为玩家2获胜
            log.info("玩家{}掉线，玩家{}获胜", user1.getUserId(), user2.getUserId());
            resp.setWinner(user2.getUserId());
        }
        if(session2 == null){
            log.info("玩家{}掉线，玩家{}获胜", user2.getUserId(), user1.getUserId());
            resp.setWinner(user1.getUserId());
        }
        if(session1 != null){
            session1.sendMessage(new TextMessage(objectMapper.writeValueAsString(resp)));
        }
        if(session2 != null){
            session2.sendMessage(new TextMessage(objectMapper.writeValueAsString(resp)));
        }

        //若此时胜负已分则销毁房间
        if(resp.getWinner() != 0){
            log.info("胜负已分，销毁房间{}",roomId);

            //更新玩家信息
            int winnerUser = resp.getWinner();
            int loserUser = (resp.getWinner() == user1.getUserId() ? user2.getUserId() : user1.getUserId());
            userMapper.updateWinner(winnerUser);
            userMapper.updateLoser(loserUser);

            roomManager.remove(roomId, user1.getUserId(), user2.getUserId());
        }

    }

//    private void printChessBoard() {
//        for(int i = 0; i < MAX_ROW; i++){
//            for(int j = 0; j < MAX_COL; j++){
//                System.out.print(chessBoard[i][j]);
//            }
//            System.out.println();
//        }
//    }

    private int checkWinner(int row, int col, int chess) {
        // 判定胜负分出四种情况，同一行、同一列、左对角线、右对角线，下面针对这些情况一一做出判定

        // 同一行的情况，列变换，根据最左边棋子的位置来进行坐标变换
        for(int c = col - 4; c <= col; c++){
            try{
                if(chessBoard[row][c] == chess
                        && chessBoard[row][c+1] == chess
                        && chessBoard[row][c+2] == chess
                        && chessBoard[row][c+3] == chess
                        && chessBoard[row][c+4] == chess){
                    return chess == 1 ? user1.getUserId() : user2.getUserId();
                }
            }catch (ArrayIndexOutOfBoundsException e){
                continue;
            }

        }

        // 同一列的情况，行标变换
        for(int r = row -4; r <= row; r++){
            try{
                if(chessBoard[r][col] == chess
                        && chessBoard[r+1][col] == chess
                        && chessBoard[r+2][col] == chess
                        && chessBoard[r+3][col] == chess
                        && chessBoard[r+4][col] == chess){
                    return chess == 1 ? user1.getUserId() : user2.getUserId();
                }
            }catch (ArrayIndexOutOfBoundsException e){
                continue;
            }
        }

        // 判断左对角线
        for(int r = row - 4, c = col - 4; r <= row && c <= col; r++,c++){
            try{
                if(chessBoard[r][c] == chess
                        && chessBoard[r+1][c+1] == chess
                        && chessBoard[r+2][c+2] == chess
                        && chessBoard[r+3][c+3] == chess
                        && chessBoard[r+4][c+4] == chess){
                    return chess == 1 ? user1.getUserId() : user2.getUserId();
                }
            }catch (ArrayIndexOutOfBoundsException e){
                continue;
            }

        }

        //判断右对角线
        for(int r = row - 4, c = col + 4; r <= row && c >= col; r++,c--){
            try{
                if(chessBoard[r][c] == chess
                        && chessBoard[r+1][c-1] == chess
                        && chessBoard[r+2][c-2] == chess
                        && chessBoard[r+3][c-3] == chess
                        && chessBoard[r+4][c-4] == chess){
                    return chess == 1 ? user1.getUserId() : user2.getUserId();
                }
            }catch (ArrayIndexOutOfBoundsException e){
                continue;
            }

        }

        // 胜负未分则返回0
        return 0;
    }
}
